package com.ldk.base.framework.util.push;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;

import cn.jpush.api.common.ClientConfig;
import cn.jpush.api.common.resp.APIConnectionException;
import cn.jpush.api.common.resp.APIRequestException;
import cn.jpush.api.device.DeviceClient;
import cn.jpush.api.push.PushClient;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Message;
import cn.jpush.api.push.model.Options;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.notification.IosNotification;
import cn.jpush.api.push.model.notification.Notification;

/**
 * 极光推送调度器
 * 支持多个极光应用的切换推送
 * @author xiangwl
 * @date  2016-07-04
 */
public final class JPushDispatcher {
	
	private final Logger logger = LoggerFactory.getLogger(JPushDispatcher.class);
	
	private Map<String, PushClient> clients;
	private Map<String, DeviceClient> devices;
	
	private static JPushDispatcher instance;
	public synchronized static JPushDispatcher getInstance(){
		if(null == instance){
			instance = new JPushDispatcher();
		}
		return instance;
	}
	
	private JPushDispatcher(){
		clients = new HashMap<String, PushClient>();
		devices = new HashMap<String, DeviceClient>();
	}
	
	/**
	 * 获取推送客户端
	 * @param key
	 * @return
	 */
	private PushClient getPushClient(String key){
		if(clients == null || !clients.containsKey(key)){
			return null;
		}
		return clients.get(key);
	}
	
	/**
	 * 获取设备客户端
	 * @param key
	 * @return
	 */
	private DeviceClient getDeviceClient(String key){
		if(clients == null || !clients.containsKey(key)){
			return null;
		}
		return devices.get(key);
	}
	
	/**
	 * 注册极光推送
	 * @param key 
	 * @param masterSecret
	 * @param appKey
	 * @param apnsProduction true 生成环境 false 开发环境
	 * @return
	 */
	public Boolean register(String key, String masterSecret, String appKey, Boolean apnsProduction) {
		ClientConfig config = ClientConfig.getInstance();
		config.setApnsProduction(apnsProduction);
		
		PushClient pushClient = new PushClient(masterSecret, appKey, null, config);
		clients.put(key, pushClient);
		
		DeviceClient deviceClient = new DeviceClient(masterSecret, appKey, null, config);
		devices.put(key, deviceClient);
		
		return true;
	}
	
	public Boolean deleteTag(String key, String theTag, String platform ){
		DeviceClient deviceClient = getDeviceClient(key);
		if(deviceClient == null){
			logger.error("极光推送未注册，请先注册");
			return false;
		}
		try{
			deviceClient.deleteTag(theTag, platform);
		}
		catch(Exception e){
			logger.error(e.getMessage());
		}
		return false;
	}
	
	

	public Boolean alertAll(String key, String alert, Map<String, String> extras) {
		PushClient pushClient = getPushClient(key);
		if(pushClient == null){
			logger.error("极光推送未注册，请先注册");
			return false;
		}
		try{
			PushPayload payload = PushPayload.alertAll(alert, null);
			PushResult result =  pushClient.sendPush(payload);
			return result != null &&  result.msg_id > 0 && result.sendno > 0;
		}
		catch(Exception e){
			logger.error(e.getMessage());
		}
		return false;
	}
	
	public Boolean alertWithAlias(String key, String title, String alert, Map<String, String> extras, List<String> aliasList) {
		PushClient pushClient = getPushClient(key);
		if(pushClient == null){
			logger.error("极光推送未注册，请先注册");
			return false;
		}
		try{
			if(aliasList == null || aliasList.isEmpty()) 
				return false;
			List<String> temp = new ArrayList<String>();
			for (String alia : aliasList) {
				if (!StringUtils.isBlank(alia))
					temp.add(alia);
			}
			if(temp.isEmpty()) return false;
			int len = temp.size();
			String[] alias = new String[len];
			int index = 0;
			for (String item : temp) {
				alias[index] = item;
				index++;
			}
			Boolean iosPushed = false;
			Boolean androidPushed = false;
			try {
				PushPayload payload = PushPayload
						.newBuilder()
						.setPlatform(Platform.android())
						.setAudience(Audience.alias(alias))
						.setNotification(Notification.android(alert, title, extras))
						.build();

				PushResult androidResult = pushClient.sendPush(payload);
				androidPushed = androidResult != null && androidResult.msg_id > 0 && androidResult.sendno > 0;
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
			try{
				PushPayload payload = PushPayload
						.newBuilder()
						.setPlatform(Platform.ios())
						.setAudience(Audience.alias(alias))
						.setNotification(Notification.ios(alert, extras))
						.build();

				PushResult iosResult = pushClient.sendPush(payload);
				iosPushed = iosResult != null && iosResult.msg_id > 0 && iosResult.sendno > 0;
			}
			catch(Exception e){
				logger.error(e.getMessage());
			}
			
			return androidPushed || iosPushed;
		}
		catch(Exception e){
			logger.error(e.getMessage());
		}
		return false;
	}

	public Boolean alertWithRegistrationID(String key, String title, String alert, Map<String, String> extras, List<String> registrationIDList) {
		PushClient pushClient = getPushClient(key);
		if(pushClient == null){
			logger.error("极光推送未注册，请先注册");
			return false;
		}
		try{
			if(registrationIDList == null || registrationIDList.isEmpty())
				return false;
			int len = registrationIDList.size();
			String[] ids = new String[len];
			int index = 0;
			for (String item : registrationIDList) {
				ids[index] = item;
			}
			Boolean iosPushed = false;
			Boolean androidPushed = false;
			try{
				PushPayload payload = PushPayload
						.newBuilder()
						.setPlatform(Platform.android())
						.setAudience(Audience.registrationId(ids))
						.setNotification(Notification.android(alert, title, extras))
						.build();

				PushResult androidResult = pushClient.sendPush(payload);
				androidPushed = androidResult != null && androidResult.msg_id > 0 && androidResult.sendno > 0;
			}
			catch(Exception e){
				logger.error(e.getMessage());
			}
			try{
				PushPayload payload = PushPayload
						.newBuilder()
						.setPlatform(Platform.ios())
						.setAudience(Audience.registrationId(ids))
						.setNotification(Notification.ios(alert, extras))
						.build();

				PushResult iosResult = pushClient.sendPush(payload);
				iosPushed = iosResult != null && iosResult.msg_id > 0 && iosResult.sendno > 0;
			}
			catch(Exception e){
				logger.error(e.getMessage());
			}
			
			return androidPushed || iosPushed;
		}
		catch(Exception e){
			logger.error(e.getMessage());
		}
		return false;
	}

	/**
	 * 
	 * @param key
	 * @param msgContent
	 * @param extras 键值对不能有null存在
	 * @return
	 */
	public Boolean messageAll(String key, String msgContent, Map<String, String> extras) {
		PushClient pushClient = getPushClient(key);
		if(pushClient == null){
			logger.error("极光推送未注册，请先注册");
			return false;
		}
		try{
			if(StringUtils.isBlank(msgContent))
				return false;
			
			PushPayload payload = PushPayload.newBuilder()
	                .setPlatform(Platform.all())
	                .setAudience(Audience.all())
	                .setMessage(Message.newBuilder()
	                        .setMsgContent(msgContent)
	                        .addExtras(extras)
	                        .build())
	                .setOptions(Options.sendno())
	                .build();
			
			PushResult result = pushClient.sendPush(payload);
			
			return result != null && result.msg_id > 0 && result.sendno > 0;
		}
		catch(APIConnectionException ae){
			logger.error(ae.getMessage());
		}
		catch (APIRequestException re) {
			logger.error(re.getMessage());
		}
		catch(Exception e){
			logger.error(e.getMessage());
		}
		return false;
	}

	/**
	 * 
	 * @param key
	 * @param title
	 * @param msgContent
	 * @param extras 键值对不能有null存在
	 * @param aliasList 
	 * @return
	 */
	public Boolean messageWithAlias(String key, String title, String msgContent, Map<String, String> extras, List<String> aliasList) {
		PushClient pushClient = getPushClient(key);
		if(pushClient == null){
			logger.error("极光推送未注册，请先注册");
			return false;
		}
		try{
			if(StringUtils.isBlank(msgContent))
				return false;
			if(aliasList == null || aliasList.isEmpty()) 
				return false;
			List<String> temp = new ArrayList<String>();
			for (String alia : aliasList) {
				if (!StringUtils.isBlank(alia))
					temp.add(alia);
			}
			if(temp.isEmpty()) return false;
			int len = temp.size();
			String[] alias = new String[len];
			int index = 0;
			for (String item : temp) {
				alias[index] = item;
				index++;
			}
			Boolean iosPushed = false;
			Boolean androidPushed = false;
			try {
				PushPayload payload = PushPayload
						.newBuilder()
						.setPlatform(Platform.android())
						.setAudience(Audience.alias(alias))
		                .setMessage(Message.newBuilder()
		                        .setTitle(title)
		                        .setMsgContent(msgContent)
		                        .addExtras(extras)
		                        .build())
						.build();

				PushResult androidResult = pushClient.sendPush(payload);
				androidPushed = androidResult != null && androidResult.msg_id > 0 && androidResult.sendno > 0;
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
			try{
				PushPayload payload = PushPayload
						.newBuilder()
						.setPlatform(Platform.ios())
						.setAudience(Audience.alias(alias))
		                .setMessage(Message.newBuilder()
		                        .setTitle(title)
		                        .setMsgContent(msgContent)
		                        .addExtras(extras)
		                        .build())
						.build();

				PushResult iosResult = pushClient.sendPush(payload);
				iosPushed = iosResult != null && iosResult.msg_id > 0 && iosResult.sendno > 0;
			}
			catch(Exception e){
				logger.error(e.getMessage());
			}
			
			return androidPushed || iosPushed;
			
		}
		catch(Exception e){
			logger.error(e.getMessage());
		}
		return false;
	}

	public Boolean messageWithRegistrationID(String key, String title, String msgContent, Map<String, String> extras, List<String> registrationIDList) {
		PushClient pushClient = getPushClient(key);
		if(pushClient == null){
			logger.error("极光推送未注册，请先注册");
			return false;
		}
		try{
			if(StringUtils.isBlank(msgContent))
				return false;
			if(registrationIDList == null || registrationIDList.isEmpty()) 
				return false;
			int len = registrationIDList.size();
			String[] ids = new String[len];
			int index = 0;
			for (String item : registrationIDList) {
				ids[index] = item;
			}
			Boolean iosPushed = false;
			Boolean androidPushed = false;
			try{
				PushPayload payload = PushPayload
						.newBuilder()
						.setPlatform(Platform.android())
						.setAudience(Audience.registrationId(ids))
		                .setMessage(Message.newBuilder()
		                        .setTitle(title)
		                        .setMsgContent(msgContent)
		                        .addExtras(extras)
		                        .build())
						.build();

				PushResult androidResult = pushClient.sendPush(payload);
				androidPushed = androidResult != null && androidResult.msg_id > 0 && androidResult.sendno > 0;
			}
			catch(Exception e){
				logger.error(e.getMessage());
			}
			try{
				PushPayload payload = PushPayload
						.newBuilder()
						.setPlatform(Platform.ios())
						.setAudience(Audience.registrationId(ids))
		                .setMessage(Message.newBuilder()
		                        .setTitle(title)
		                        .setMsgContent(msgContent)
		                        .addExtras(extras)
		                        .build())
						.build();

				PushResult iosResult = pushClient.sendPush(payload);
				iosPushed = iosResult != null && iosResult.msg_id > 0 && iosResult.sendno > 0;
			}
			catch(Exception e){
				logger.error(e.getMessage());
			}
			
			return androidPushed || iosPushed;
		}
		catch(Exception e){
			logger.error(e.getMessage());
		}
		return false;
	}

	/**
	 * 通知消息推送
	 * @param key
	 * @param title
	 * @param message
	 * @param extras
	 * @param aliasList
	 * @return
	 */
	public Boolean notificationAndMessageWithAlias(String key, String title, String message, Map<String, String> extras, List<String> aliasList){
		PushClient pushClient = getPushClient(key);
		if(pushClient == null){
			logger.error("极光推送未注册，请先注册");
			return false;
		}
		if(StringUtils.isBlank(message))
			return false;
		if(aliasList == null || aliasList.isEmpty()) 
			return false;
		List<String> temp = new ArrayList<String>();
		for (String alia : aliasList) {
			if (!StringUtils.isBlank(alia))
				temp.add(alia);
		}
		if(temp.isEmpty()) return false;
		int len = temp.size();
		String[] alias = new String[len];
		int index = 0;
		for (String item : temp) {
			alias[index] = item;
			index++;
		}
		Boolean iosPushed = false;
		Boolean androidPushed = false;
		try{
			IosNotification iosNotification = IosNotification.newBuilder()
					.setAlert(message)
					.setSound("default")
					.addExtras(extras)
					.setBadge(1)
					.build();
			Notification notification = Notification.newBuilder()
					.addPlatformNotification(iosNotification)
					.build();
			//ios加通知推送
			PushPayload payload = PushPayload.newBuilder()
	                .setPlatform(Platform.ios())
	                .setAudience(Audience.alias(alias))
	                .setNotification(notification)
	                .build();
			PushResult result = pushClient.sendPush(payload);
			iosPushed = result != null && result.msg_id > 0 && result.sendno > 0;
		}
		catch(APIConnectionException ae){
			logger.error(ae.getMessage());
		}
		catch (APIRequestException re) {
			logger.error(re.getMessage());
		}
		catch(Exception e){
			logger.error(e.getMessage());
		}
		//android
		try{
			//android
			PushPayload payload = PushPayload.newBuilder()
	                .setPlatform(Platform.android())
	                .setAudience(Audience.alias(alias))
	                .setMessage(Message.newBuilder()
	                        .setTitle(title)
	                        .setMsgContent(message)
	                        .addExtras(extras)
	                        .build())
	                .build();
			PushResult result = pushClient.sendPush(payload);
			androidPushed = result != null && result.msg_id > 0 && result.sendno > 0;
		}
		catch(APIConnectionException ae){
			logger.error(ae.getMessage());
		}
		catch (APIRequestException re) {
			logger.error(re.getMessage());
		}
		catch(Exception e){
			logger.error(e.getMessage());
		}
		return iosPushed ||  androidPushed;
	}
	
	/**
	 * 通知消息推送
	 * @param key
	 * @param title
	 * @param message
	 * @param extras
	 * @param aliasList
	 * @return
	 */
	public Boolean notificationAndMessageAll(String key, String title, String message, Map<String, String> extras){
		PushClient pushClient = getPushClient(key);
		if(pushClient == null){
			logger.error("极光推送未注册，请先注册");
			return false;
		}
		if(StringUtils.isBlank(message))
			return false;
		
		Boolean iosPushed = false;
		Boolean androidPushed = false;
		try{
			IosNotification iosNotification = IosNotification.newBuilder()
					.setAlert(message)
					.setSound("default")
					.addExtras(extras)
					.setBadge(1)
					.build();
			Notification notification = Notification.newBuilder()
					.addPlatformNotification(iosNotification)
					.build();
			//ios加通知推送
			PushPayload payload = PushPayload.newBuilder()
	                .setPlatform(Platform.ios())
	                .setAudience(Audience.all())
	                .setNotification(notification)
	                .build();
			PushResult result = pushClient.sendPush(payload);
			iosPushed = result != null && result.msg_id > 0 && result.sendno > 0;
		}
		catch(APIConnectionException ae){
			logger.error(ae.getMessage());
		}
		catch (APIRequestException re) {
			logger.error(re.getMessage());
		}
		catch(Exception e){
			logger.error(e.getMessage());
		}
		//android
		try{
			//android
			PushPayload payload = PushPayload.newBuilder()
	                .setPlatform(Platform.android())
	                .setAudience(Audience.all())
	                .setMessage(Message.newBuilder()
	                        .setTitle(title)
	                        .setMsgContent(message)
	                        .addExtras(extras)
	                        .build())
	                .build();
			PushResult result = pushClient.sendPush(payload);
			androidPushed = result != null && result.msg_id > 0 && result.sendno > 0;
		}
		catch(APIConnectionException ae){
			logger.error(ae.getMessage());
		}
		catch (APIRequestException re) {
			logger.error(re.getMessage());
		}
		catch(Exception e){
			logger.error(e.getMessage());
		}
		return iosPushed ||  androidPushed;
	}
	
	/**
	 * 安卓根据别名推送消息（透传）
	 * @param key
	 * @param title
	 * @param message
	 * @param extras
	 * @param aliasList
	 * @return
	 */
	public Boolean androidMessageWithAlias(String key, String title, String message, Map<String, String> extras, List<String> aliasList){
		PushClient pushClient = getPushClient(key);
		if(pushClient == null){
			logger.error("极光推送未注册，请先注册");
			return false;
		}
		if(StringUtils.isBlank(message))
			return false;
		if(aliasList == null || aliasList.isEmpty()) 
			return false;
		//logger.error("androidMessageWithAlias.aliasList="+JSON.toJSONString(aliasList));
		List<String> temp = new ArrayList<String>();
		for (String alia : aliasList) {
			if (!StringUtils.isBlank(alia))
				temp.add(alia);
		}
		if(temp.isEmpty()) return false;
		int len = temp.size();
		String[] alias = new String[len];
		int index = 0;
		for (String item : temp) {
			alias[index] = item;
			index++;
		}
		//logger.error("androidMessageWithAlias.alias="+JSON.toJSONString(alias));
		Boolean androidPushed = false;
		try{
			PushPayload payload = PushPayload.newBuilder()
	                .setPlatform(Platform.android())
	                .setAudience(Audience.alias(alias))
	                .setMessage(Message.newBuilder()
	                        .setTitle(title)
	                        .setMsgContent(message)
	                        .addExtras(extras)
	                        .build())
	                .build();
			PushResult result = pushClient.sendPush(payload);
			logger.error("androidMessageWithAlias.result="+JSON.toJSONString(result));
			androidPushed = result != null &&  result.msg_id > 0 && result.sendno > 0;
		}
		catch(Exception e){
			logger.error("androidMessageWithAlias.error="+e.getMessage());
		}
		return androidPushed;
	}
	/**
	 * 安卓推送消息到所有设备（透传）
	 * @param key
	 * @param title
	 * @param message
	 * @param extras
	 * @return
	 */
	public Boolean androidMessageAll(String key, String title, String message, Map<String, String> extras){
		PushClient pushClient = getPushClient(key);
		if(pushClient == null){
			logger.error("极光推送未注册，请先注册");
			return false;
		}
		if(StringUtils.isBlank(message))
			return false;
		Boolean androidPushed = false;
		try{
			PushPayload payload = PushPayload.newBuilder()
	                .setPlatform(Platform.android())
	                .setAudience(Audience.all())
	                .setMessage(Message.newBuilder()
	                        .setTitle(title)
	                        .setMsgContent(message)
	                        .addExtras(extras)
	                        .build())
	                .build();
			PushResult result = pushClient.sendPush(payload);
			androidPushed = result != null &&  result.msg_id > 0 && result.sendno > 0;
		}
		catch(Exception e){
			logger.error(e.getMessage());
		}
		return androidPushed;
	}
	
	/**
	 * IOS根据别名推送消息
	 * @param key
	 * @param alert 推送消息
	 * @param sound 为空时默认为default
	 * @param extras 自定义消息
	 * @param aliasList 别名列表
	 * @return true推送成功false推送失败
	 */
	public Boolean iosNotificationWithAlias(String key, String alert, String sound, Map<String, String> extras, List<String> aliasList){
		PushClient pushClient = getPushClient(key);
		if(pushClient == null){
			logger.error("极光推送未注册，请先注册");
			return false;
		}
		if(StringUtils.isBlank(alert))
			return false;
		if(StringUtils.isBlank(sound)){
			sound = "default";
		}
		if(aliasList == null || aliasList.isEmpty()) 
			return false;
		List<String> temp = new ArrayList<String>();
		for (String alia : aliasList) {
			if (!StringUtils.isBlank(alia))
				temp.add(alia);
		}
		if(temp.isEmpty()) return false;
		int len = temp.size();
		String[] alias = new String[len];
		int index = 0;
		for (String item : temp) {
			alias[index] = item;
			index++;
		}
		
		Boolean iosPushed = false;
		try{
			IosNotification iosNotification = IosNotification.newBuilder()
					.setAlert(alert)
					.setSound(sound)
					.addExtras(extras)
					.setBadge(1)
					.build();
			Notification notification = Notification.newBuilder()
					.addPlatformNotification(iosNotification)
					.build();
			//ios加通知推送
			PushPayload payload = PushPayload.newBuilder()
	                .setPlatform(Platform.ios())
	                .setAudience(Audience.alias(alias))
	                .setNotification(notification)
	                .build();
			PushResult result = pushClient.sendPush(payload);
			logger.error("iosNotificationWithAlias.result="+JSON.toJSONString(result));
			iosPushed = result != null && result.msg_id > 0 && result.sendno > 0;
		}
		catch(Exception e){
			logger.error("iosNotificationWithAlias.error="+e.getMessage());
		}
		return iosPushed;
	}
	
	/**
	 * IOS推送消息到所有设备
	 * @param key
	 * @param alert 推送消息
	 * @param sound 为空时默认为default
	 * @param extras 自定义消息
	 * @return true推送成功false推送失败
	 */
	public Boolean iosNotificationAll(String key, String alert, String sound, Map<String, String> extras){
		PushClient pushClient = getPushClient(key);
		if(pushClient == null){
			logger.error("极光推送未注册，请先注册");
			return false;
		}
		if(StringUtils.isBlank(alert))
			return false;
		if(StringUtils.isBlank(sound)){
			sound = "default";
		}
		
		Boolean iosPushed = false;
		try{
			IosNotification iosNotification = IosNotification.newBuilder()
					.setAlert(alert)
					.setSound(sound)
					.addExtras(extras)
					.setBadge(1)
					.build();
			Notification notification = Notification.newBuilder()
					.addPlatformNotification(iosNotification)
					.build();
			//ios加通知推送
			PushPayload payload = PushPayload.newBuilder()
	                .setPlatform(Platform.ios())
	                .setAudience(Audience.all())
	                .setNotification(notification)
	                .build();
			PushResult result = pushClient.sendPush(payload);
			iosPushed = result != null && result.msg_id > 0 && result.sendno > 0;
		}
		catch(Exception e){
			logger.error(e.getMessage());
		}
		return iosPushed;
	}
	
	/**
	 * 带铃声的推送消息到安卓和IOS手机
	 * @param key
	 * @param title
	 * @param message
	 * @param sound
	 * @param extras
	 * @param aliasList
	 * @return
	 */
	public Boolean pushWithAliasAndSound(String key, String title, String message, String sound, Map<String, String> extras, List<String> aliasList){
		Boolean iosPushed = false;
		Boolean androidPushed = false;
		
		iosPushed = iosNotificationWithAlias(key, message, sound, extras, aliasList);
		androidPushed = androidMessageWithAlias(key, title, message, extras, aliasList);
		
		return iosPushed || androidPushed;
	}
	
	/**
	 * 带铃声的推送消息到安卓和IOS手机
	 * @param key
	 * @param title
	 * @param message
	 * @param sound
	 * @param extras
	 * @return
	 */
	public Boolean pushAllWithSound(String key, String title, String message, String sound, Map<String, String> extras){
		Boolean iosPushed = false;
		Boolean androidPushed = false;
		
		iosPushed = iosNotificationAll(key, message, sound, extras);
		androidPushed = androidMessageAll(key, title, message, extras);
		
		return iosPushed || androidPushed;
	}
}
